home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1993 July / InfoMagic USENET CD-ROM July 1993.ISO / sources / unix / volume18 / undel / part04 < prev    next >
Encoding:
Text File  |  1989-05-06  |  25.5 KB  |  1,064 lines

  1. Path: uunet!bbn.com!rsalz
  2. From: rsalz@uunet.uu.net (Rich Salz)
  3. Newsgroups: comp.sources.unix
  4. Subject: v18i076:  MIT Athena delete/undelete programs, Part04/06
  5. Message-ID: <1636@fig.bbn.com>
  6. Date: 29 Mar 89 04:32:41 GMT
  7. Lines: 1052
  8. Approved: rsalz@uunet.UU.NET
  9.  
  10. Submitted-by: Jonathan I. Kamens <jik@PIT-MANAGER.MIT.EDU>
  11. Posting-number: Volume 18, Issue 76
  12. Archive-name: undel/part04
  13.  
  14. #! /bin/sh
  15. # This is a shell archive.  Remove anything before this line, then unpack
  16. # it by saving it into a file and typing "sh file".  To overwrite existing
  17. # files, type "sh file -c".  You can also feed this as standard input via
  18. # unshar, or by typing "sh <file", e.g..  If this archive is complete, you
  19. # will see the following message at the end:
  20. #        "End of archive 4 (of 6)."
  21. # Contents:  expunge.c pattern.c
  22. # Wrapped by jik@pit-manager on Mon Mar 27 12:16:51 1989
  23. PATH=/bin:/usr/bin:/usr/ucb ; export PATH
  24. if test -f 'expunge.c' -a "${1}" != "-c" ; then 
  25.   echo shar: Will not clobber existing file \"'expunge.c'\"
  26. else
  27. echo shar: Extracting \"'expunge.c'\" \(10893 characters\)
  28. sed "s/^X//" >'expunge.c' <<'END_OF_FILE'
  29. X/*
  30. X * $Source: /mit/jik/src/delete/RCS/expunge.c,v $
  31. X * $Author: jik $
  32. X *
  33. X * This program is part of a package including delete, undelete,
  34. X * lsdel, expunge and purge.  The software suite is meant as a
  35. X * replacement for rm which allows for file recovery.
  36. X * 
  37. X * Copyright (c) 1989 by the Massachusetts Institute of Technology.
  38. X * For copying and distribution information, see the file "mit-copyright.h."
  39. X */
  40. X
  41. X#if (!defined(lint) && !defined(SABER))
  42. X     static char rcsid_expunge_c[] = "$Header: expunge.c,v 1.7 89/03/27 12:06:47 jik Exp $";
  43. X#endif
  44. X
  45. X/*
  46. X * Things that need to be fixed later:
  47. X *
  48. X * 1. The program should somehow store the sizes of deleted files and
  49. X * report the total amount of space regained after an expunge or purge.
  50. X */
  51. X
  52. X#include <stdio.h>
  53. X#include <sys/types.h>
  54. X#include <sys/time.h>
  55. X#include <sys/dir.h>
  56. X#include <sys/param.h>
  57. X#include <strings.h>
  58. X#include <sys/stat.h>
  59. X#include "col.h"
  60. X#include "directories.h"
  61. X#include "util.h"
  62. X#include "pattern.h"
  63. X#include "expunge.h"
  64. X#include "mit-copyright.h"
  65. X
  66. Xextern char *malloc(), *realloc();
  67. Xextern int current_time;
  68. X
  69. Xchar *whoami, *error_buf;
  70. X
  71. Xint  timev,        /* minimum mod time before undeletion */
  72. X     interactive,    /* query before each expunge */
  73. X     recursive,        /* expunge undeleted directories recursively */
  74. X     noop,        /* print what would be done instead of doing it */
  75. X     verbose,        /* print a line as each file is deleted */
  76. X     force,        /* do not ask for any confirmation */
  77. X     listfiles,        /* list files at toplevel */
  78. X     yield;        /* print yield of expunge at end */
  79. X
  80. Xint blocks_removed = 0;
  81. X
  82. X
  83. X
  84. X
  85. Xmain(argc, argv)
  86. Xint argc;
  87. Xchar *argv[];
  88. X{
  89. X     extern char *optarg;
  90. X     extern int optind;
  91. X     int arg;
  92. X     int status = 0;
  93. X
  94. X     whoami = lastpart(argv[0]);
  95. X     error_buf = malloc(strlen(whoami) + MAXPATHLEN + 3);
  96. X     if (! error_buf) {
  97. X      perror(whoami);
  98. X      exit(1);
  99. X     }
  100. X     if (*whoami == 'p') { /* we're doing a purge */
  101. X      exit (purge());
  102. X     }
  103. X     timev = 0;
  104. X     yield = interactive = recursive = noop = verbose = listfiles = force = 0;
  105. X     while ((arg = getopt(argc, argv, "t:irfnvly")) != -1) {
  106. X      switch (arg) {
  107. X      case 't':
  108. X           timev = atoi(optarg);
  109. X           break;
  110. X      case 'i':
  111. X           interactive++;
  112. X           break;
  113. X      case 'r':
  114. X           recursive++;
  115. X           break;
  116. X      case 'f':
  117. X           force++;
  118. X           break;
  119. X      case 'n':
  120. X           noop++;
  121. X           break;
  122. X      case 'v':
  123. X           verbose++;
  124. X           break;
  125. X      case 'l':
  126. X           listfiles++;
  127. X           break;
  128. X      case 'y':
  129. X           yield++;
  130. X           break;
  131. X      default:
  132. X           usage();
  133. X           exit(1);
  134. X      }
  135. X     }
  136. X     if (optind == argc) {
  137. X      char *dir;
  138. X      dir = ".";
  139. X      status = status | expunge(&dir, 1); /* current working directory */
  140. X     }
  141. X     else
  142. X      status = status | expunge(&argv[optind], argc - optind);
  143. X     exit(status & ERROR_MASK);
  144. X}
  145. X
  146. X
  147. X
  148. X
  149. X
  150. Xpurge()
  151. X{
  152. X     char *home[1];
  153. X
  154. X     home[0] = malloc(MAXPATHLEN);
  155. X     if (! home[0]) {
  156. X      perror(sprintf(error_buf, "%s: purge", whoami));
  157. X      exit(1);
  158. X     }
  159. X     timev = interactive = noop = verbose = force = 0;
  160. X     yield = listfiles = recursive = 1;
  161. X     get_home(home[0]);
  162. X     if (! *home[0]) {
  163. X      fprintf(stderr, "%s: purge: can't get home directory\n", whoami);
  164. X      exit(1);
  165. X     }
  166. X
  167. X     printf("Please be patient.... this may take a while.\n\n");
  168. X     
  169. X     return(expunge(home, 1));
  170. X}
  171. X
  172. X
  173. X
  174. X
  175. Xusage()
  176. X{
  177. X     printf("Usage: %s [ options ] [ filename [ ... ]]\n", whoami);
  178. X     printf("Options are:\n");
  179. X     printf("     -r     recursive\n");
  180. X     printf("     -i     interactive\n");
  181. X     printf("     -f     force\n");
  182. X     printf("     -t n   n-day-or-older expunge\n");
  183. X     printf("     -n     noop\n");
  184. X     printf("     -v     verbose\n");
  185. X     printf("     -l     list files before expunging\n");
  186. X     printf("     -y     print yield of expunge\n");
  187. X     printf("     --     end options and start filenames\n");
  188. X}
  189. X
  190. X
  191. X
  192. X
  193. X
  194. Xexpunge(files, num)
  195. Xchar **files;
  196. Xint num;
  197. X{
  198. X     char *file_re;
  199. X     char **found_files;
  200. X     int num_found;
  201. X     char *start_dir;
  202. X     int status = 0;
  203. X     int total = 0;
  204. X     filerec *current;
  205. X     
  206. X     if (initialize_tree())
  207. X      exit(1);
  208. X
  209. X     for ( ; num ; num--) {
  210. X      if (*files[num - 1] == '/') {
  211. X           start_dir = "/";
  212. X           file_re = parse_pattern(files[num - 1] + 1);
  213. X      }
  214. X      else {
  215. X           start_dir = "";
  216. X           file_re = parse_pattern(files[num - 1]);
  217. X      }
  218. X      if (! file_re)
  219. X           return(ERROR_MASK);
  220. X      
  221. X      found_files = get_the_files(start_dir, file_re, &num_found);
  222. X      if (num_found)
  223. X           num_found = process_files(found_files, num_found);
  224. X      total += num_found;
  225. X      if (! num_found) if (! force) {
  226. X           /*
  227. X        * There are three different situations here.  Eiter we
  228. X        * are dealing with an existing directory with no
  229. X            * deleted files in it, or we are deleting with a
  230. X            * non-existing deleted file with wildcards, or we are
  231. X            * dealing with a non-existing deleted file without
  232. X            * wildcards.  In the former case we print nothing, and
  233. X            * in the latter cases we print either "no match" or
  234. X            * "not found" respectively
  235. X        */
  236. X           if (no_wildcards(file_re)) {
  237. X            if (! directory_exists(files[num - 1])) {
  238. X             fprintf(stderr, "%s: %s: not found\n",
  239. X                 whoami, files[num - 1]);
  240. X            }
  241. X           }
  242. X           else {
  243. X            fprintf(stderr, "%s: %s: no match\n", whoami,
  244. X                files[num - 1]);
  245. X           }
  246. X      }
  247. X      free(file_re);
  248. X     }
  249. X     if (total && listfiles) {
  250. X      list_files();
  251. X      if (! force) if (! top_level())
  252. X           return(NO_DELETE_MASK);
  253. X     }
  254. X     current = get_root_tree();
  255. X     if (current)
  256. X      status = status | expunge_specified(current);
  257. X     current = get_cwd_tree();
  258. X     if (current)
  259. X      status = status | expunge_specified(current);
  260. X
  261. X     if (yield) {
  262. X      if (noop)
  263. X           printf("Total that would be expunged: %dk\n",
  264. X              blk_to_k(blocks_removed));
  265. X      else
  266. X           printf("Total expunged: %dk\n", blk_to_k(blocks_removed));
  267. X     }
  268. X     return(status);
  269. X}
  270. X
  271. X
  272. X
  273. Xexpunge_specified(leaf)
  274. Xfilerec *leaf;
  275. X{
  276. X     int status = 0;
  277. X
  278. X     if ((leaf->specified) && ((leaf->specs.st_mode & S_IFMT) == S_IFDIR))
  279. X      status = do_directory_expunge(leaf);
  280. X     /* the "do_directory_expunge" really only asks the user if he */
  281. X     /* wants to expunge the directory, it doesn't do any deleting. */
  282. X     if (! status) {
  283. X      if (leaf->dirs)
  284. X           status |= expunge_specified(leaf->dirs);
  285. X      if (leaf->files)
  286. X           status |= expunge_specified(leaf->files);
  287. X     }
  288. X     if (leaf->specified)
  289. X      status |= really_do_expunge(leaf);
  290. X     if (leaf->next)
  291. X      status |= expunge_specified(leaf->next);
  292. X     free_leaf(leaf);
  293. X     return(status);
  294. X}
  295. X
  296. X
  297. Xprocess_files(files, num)
  298. Xchar **files;
  299. Xint num;
  300. X{
  301. X     int i;
  302. X     filerec *leaf;
  303. X     
  304. X     for (i = 0; i < num; i++) {
  305. X      if (! (leaf = add_path_to_tree(files[i]))) {
  306. X           fprintf(stderr, "%s: error adding path to filename tree\n",
  307. X               whoami);
  308. X           exit(1);
  309. X      }
  310. X
  311. X      free(files[i]);
  312. X      if (! timed_out(leaf, current_time, timev)) {
  313. X           free_leaf(leaf);
  314. X           num--;
  315. X      }
  316. X     }
  317. X     free(files);
  318. X     return(num);
  319. X}
  320. X
  321. X
  322. X
  323. X
  324. X
  325. X
  326. X
  327. X
  328. X
  329. Xdo_directory_expunge(file_ent)
  330. Xfilerec *file_ent;
  331. X{
  332. X     char buf[MAXPATHLEN];
  333. X
  334. X     get_leaf_path(file_ent, buf);
  335. X     convert_to_user_name(buf, buf);
  336. X     
  337. X     if (interactive) {
  338. X      printf("%s: Expunge directory %s? ", whoami, buf);
  339. X      if (! yes())
  340. X           return(NO_DELETE_MASK);
  341. X     }
  342. X     return(0);
  343. X}
  344. X
  345. X
  346. X
  347. X
  348. X
  349. X
  350. X
  351. X
  352. Xreally_do_expunge(file_ent)
  353. Xfilerec *file_ent;
  354. X{
  355. X     char real[MAXPATHLEN], user[MAXPATHLEN];
  356. X     int status;
  357. X     
  358. X     get_leaf_path(file_ent, real);
  359. X     convert_to_user_name(real, user);
  360. X
  361. X     if (interactive) {
  362. X      printf ("%s: Expunge %s (%dk)? ", whoami, user,
  363. X          blk_to_k(file_ent->specs.st_blocks));
  364. X      if (! yes())
  365. X           return(NO_DELETE_MASK);
  366. X     }
  367. X
  368. X     if (noop) {
  369. X      blocks_removed += file_ent->specs.st_blocks;
  370. X      printf("%s: %s (%dk) would be expunged (%dk total)\n", whoami, user,
  371. X         blk_to_k(file_ent->specs.st_blocks),
  372. X         blk_to_k(blocks_removed));
  373. X      return(0);
  374. X     }
  375. X
  376. X     if ((file_ent->specs.st_mode & S_IFMT) == S_IFDIR)
  377. X      status = rmdir(real);
  378. X     else
  379. X      status = unlink(real);
  380. X     if (! status) {
  381. X      blocks_removed += file_ent->specs.st_blocks;
  382. X      if (verbose)
  383. X           printf("%s: %s (%dk) expunged (%dk total)\n", whoami, user,
  384. X              blk_to_k(file_ent->specs.st_blocks),
  385. X              blk_to_k(blocks_removed));
  386. X      return(0);
  387. X     }
  388. X     else {
  389. X      if (! force)
  390. X           fprintf(stderr, "%s: %s not expunged\n", whoami, user);
  391. X      return(ERROR_MASK);
  392. X     }
  393. X}
  394. X
  395. X
  396. X
  397. X
  398. X
  399. X
  400. X
  401. X
  402. X
  403. Xtop_level()
  404. X{
  405. X     if (interactive) {
  406. Xprintf("The above files, which have been marked for deletion, are about to be\n");
  407. Xprintf("expunged forever!  You will be asked for confirmation before each file is\n");
  408. Xprintf("deleted.  Do you wish to continue [return = no]? ");
  409. X     }
  410. X     else {
  411. Xprintf("The above files, which have been marked for deletion, are about to be\n");
  412. Xprintf("expunged forever!  Make sure you don't need any of them before continuing.\n");
  413. Xprintf("Do you wish to continue [return = no]? ");
  414. X     }
  415. X     return (yes());
  416. X}
  417. X
  418. X
  419. X
  420. X
  421. X
  422. Xlist_files()
  423. X{
  424. X     filerec *current;
  425. X     char **strings;
  426. X     int num;
  427. X     
  428. X     strings = (char **) malloc(sizeof(char *));
  429. X     num = 0;
  430. X     if (! strings) {
  431. X      if (! force)
  432. X           perror(sprintf(error_buf, "%s: list_files", whoami));
  433. X      exit(1);
  434. X     }
  435. X     printf("The following deleted files are going to be expunged: \n\n");
  436. X
  437. X     current = get_root_tree();
  438. X     strings = accumulate_names(current, strings, &num);
  439. X     current = get_cwd_tree();
  440. X     strings = accumulate_names(current, strings, &num);
  441. X     column_array(strings, num, DEF_SCR_WIDTH, 0, 0, 2, 1, 0, 1, stdout);
  442. X     printf("\n");
  443. X     return(0);
  444. X}
  445. X     
  446. X
  447. X
  448. X
  449. X
  450. Xchar **get_the_files(base, reg_exp, num_found)
  451. Xchar *base, *reg_exp;
  452. Xint *num_found;
  453. X{
  454. X     char **matches;
  455. X     int num_matches;
  456. X     char **found;
  457. X     int num;
  458. X     int i;
  459. X     
  460. X     found = (char **) malloc(0);
  461. X     num = 0;
  462. X     
  463. X     matches = find_matches(base, reg_exp, &num_matches);
  464. X     if (recursive) {
  465. X      char **recurs_found;
  466. X      int recurs_num;
  467. X      
  468. X      for (i = 0; i < num_matches; free(matches[i]), i++) {
  469. X           if (is_deleted(lastpart(matches[i]))) {
  470. X            found = add_str(found, num, matches[i]);
  471. X            num++;
  472. X           }
  473. X           recurs_found = find_deleted_recurses(matches[i], &recurs_num);
  474. X           add_arrays(&found, &num, &recurs_found, &recurs_num);
  475. X      }
  476. X     }    
  477. X     else {
  478. X      struct stat stat_buf;
  479. X      char **contents_found;
  480. X      int num_contents;
  481. X      
  482. X      for (i = 0; i < num_matches; free(matches[i]), i++) {
  483. X           if (is_deleted(lastpart(matches[i]))) {
  484. X            found = add_str(found, num, matches[i]);
  485. X            num++;
  486. X           }
  487. X           if (lstat(matches[i], &stat_buf))
  488. X            continue;
  489. X           if ((stat_buf.st_mode & S_IFMT) == S_IFDIR) {
  490. X            contents_found = find_deleted_contents_recurs(matches[i],
  491. X                                   &num_contents);
  492. X            add_arrays(&found, &num, &contents_found,
  493. X                   &num_contents);
  494. X           }
  495. X      }
  496. X     }
  497. X     free(matches);
  498. X     *num_found = num;
  499. X     return(found);
  500. X}
  501. END_OF_FILE
  502. if test 10893 -ne `wc -c <'expunge.c'`; then
  503.     echo shar: \"'expunge.c'\" unpacked with wrong size!
  504. fi
  505. # end of 'expunge.c'
  506. fi
  507. if test -f 'pattern.c' -a "${1}" != "-c" ; then 
  508.   echo shar: Will not clobber existing file \"'pattern.c'\"
  509. else
  510. echo shar: Extracting \"'pattern.c'\" \(12106 characters\)
  511. sed "s/^X//" >'pattern.c' <<'END_OF_FILE'
  512. X/*
  513. X * $Source: /mit/jik/src/delete/RCS/pattern.c,v $
  514. X * $Author: jik $
  515. X *
  516. X * This program is part of a package including delete, undelete,
  517. X * lsdel, expunge and purge.  The software suite is meant as a
  518. X * replacement for rm which allows for file recovery.
  519. X * 
  520. X * Copyright (c) 1989 by the Massachusetts Institute of Technology.
  521. X * For copying and distribution information, see the file "mit-copyright.h."
  522. X */
  523. X
  524. X#if (!defined(lint) && !defined(SABER))
  525. X     static char rcsid_pattern_c[] = "$Header: pattern.c,v 1.8 89/03/27 12:07:48 jik Exp $";
  526. X#endif
  527. X
  528. X#include <stdio.h>
  529. X#include <sys/types.h>
  530. X#include <sys/dir.h>
  531. X#include <sys/param.h>
  532. X#include <strings.h>
  533. X#include <sys/stat.h>
  534. X#include "directories.h"
  535. X#include "pattern.h"
  536. X#include "util.h"
  537. X#include "undelete.h"
  538. X#include "mit-copyright.h"
  539. X
  540. Xstatic char *add_char();
  541. X
  542. Xextern char *malloc(), *realloc();
  543. X
  544. Xextern char *whoami, *error_buf;
  545. X
  546. X/*
  547. X * parse_pattern returns an area of memory allocated by malloc when it
  548. X * is successful.  Therefore, other procedures calling parse_pattern
  549. X * should use free() to free the region of memory when they are done
  550. X * with it.
  551. X */
  552. Xchar *parse_pattern(file_pattern)
  553. Xchar *file_pattern;
  554. X{
  555. X     char *re_pattern, *cur_ptr, *re_ptr;
  556. X     int guess_length;
  557. X     
  558. X     guess_length = strlen(file_pattern) + 5;
  559. X     re_ptr = re_pattern = malloc(guess_length);
  560. X     if (! re_ptr) {
  561. X      perror(sprintf(error_buf, "%s: parse_pattern", whoami));
  562. X      exit(1);
  563. X     }
  564. X     
  565. X     for (cur_ptr = file_pattern, re_ptr = re_pattern; *cur_ptr != NULL;
  566. X      cur_ptr++) {
  567. X      if (*cur_ptr == '\\') {
  568. X           if (! cur_ptr[1]) {
  569. X            fprintf(stderr,
  570. X                "%s: parse_pattern: incomplete expression\n",
  571. X                whoami);
  572. X            return((char *) NULL);
  573. X           }
  574. X           if (! add_char(&re_pattern, &re_ptr, &guess_length, '\\'))
  575. X            return ((char *) NULL);
  576. X           cur_ptr++;
  577. X           if (! add_char(&re_pattern, &re_ptr, &guess_length, *cur_ptr))
  578. X            return ((char *) NULL);
  579. X           continue;
  580. X      }
  581. X      else if (*cur_ptr == '*') {
  582. X           if (! add_char(&re_pattern, &re_ptr, &guess_length, '.'))
  583. X            return ((char *) NULL);
  584. X           if (! add_char(&re_pattern, &re_ptr, &guess_length, '*'))
  585. X            return ((char *) NULL);
  586. X           continue;
  587. X      }
  588. X      else if (*cur_ptr == '?') {
  589. X           if (! add_char(&re_pattern, &re_ptr, &guess_length, '.'))
  590. X            return ((char *) NULL);
  591. X           continue;
  592. X      }
  593. X      else if (*cur_ptr == '.') {
  594. X           if (! add_char(&re_pattern, &re_ptr, &guess_length, '\\'))
  595. X            return ((char *) NULL);
  596. X           if (! add_char(&re_pattern, &re_ptr, &guess_length, '.'))
  597. X            return ((char *) NULL);
  598. X      }
  599. X      else {
  600. X           if (! add_char(&re_pattern, &re_ptr, &guess_length, *cur_ptr))
  601. X            return ((char *) NULL);
  602. X      }
  603. X     }
  604. X     if (! add_char(&re_pattern, &re_ptr, &guess_length, '\0'))
  605. X      return ((char *) NULL);
  606. X     return (re_pattern);
  607. X}
  608. X
  609. X
  610. X
  611. X
  612. X
  613. X
  614. X/*
  615. X * add_char() takes two char **, a length which is the current amount
  616. X * of space implemented for the string pointed to by the first *(char **),
  617. X * and a character to add to the string.  It reallocs extra space if
  618. X * necessary, adds the character, and messes with the pointers if necessary.
  619. X */
  620. Xstatic char *add_char(start, finish, length, chr)
  621. Xchar **start, **finish;
  622. Xint *length;
  623. Xchar chr;
  624. X{
  625. X     if (*finish - *start == *length) {
  626. X      *start = realloc(*start, *length + 5);
  627. X      if (! *start) {
  628. X           perror(sprintf(error_buf, "%s: add_char", whoami));
  629. X           exit(1);
  630. X      }
  631. X      *finish = *start + *length - 1;
  632. X      *length += 5;
  633. X     }
  634. X     **finish = chr;
  635. X     (*finish)++;
  636. X     return(*start);
  637. X}
  638. X
  639. X      
  640. X
  641. X
  642. X
  643. X
  644. X/*
  645. X * add_arrays() takes pointers to two arrays of char **'s and their
  646. X * lengths, merges the two into the first by realloc'ing the first and
  647. X * then free's the second's memory usage.
  648. X */  
  649. Xadd_arrays(array1, num1, array2, num2)
  650. Xchar ***array1, ***array2;
  651. Xint *num1, *num2;
  652. X{
  653. X     int counter;
  654. X     
  655. X     *array1 = (char **) realloc(*array1, sizeof(char *) * (*num1 + *num2));
  656. X     if (! *array1) {
  657. X      perror(sprintf(error_buf, "%s: add_arrays", whoami));
  658. X      exit(1);
  659. X     }
  660. X     for (counter = *num1; counter < *num1 + *num2; counter++)
  661. X      *(*array1 + counter) = *(*array2 + counter - *num1);
  662. X     free (*array2);
  663. X     *num1 += *num2;
  664. X     return(0);
  665. X}
  666. X
  667. X
  668. X
  669. X
  670. X
  671. X
  672. X
  673. Xchar **add_str(strs, num, str)
  674. Xchar **strs;
  675. Xint num;
  676. Xchar *str;
  677. X{
  678. X     strs = (char **) realloc(strs, sizeof(char *) * (num + 1));
  679. X     if (! strs) {
  680. X      perror(sprintf(error_buf, "%s: add_str", whoami));
  681. X      exit(1);
  682. X     }
  683. X     strs[num] = malloc(strlen(str) + 1);
  684. X     if (! strs[num]) {
  685. X      perror(sprintf(error_buf, "%s: add_str", whoami));
  686. X      exit(1);
  687. X     }
  688. X     strcpy(strs[num], str);
  689. X     return(strs);
  690. X}
  691. X
  692. X
  693. X
  694. X
  695. X
  696. X
  697. X
  698. Xchar **find_deleted_matches(base, expression, num_found)
  699. Xchar *base, *expression;
  700. Xint *num_found;
  701. X{
  702. X     struct direct *dp;
  703. X     DIR *dirp;
  704. X     char **found;
  705. X     int num;
  706. X     char **next;
  707. X     int num_next;
  708. X     char first[MAXNAMLEN], rest[MAXPATHLEN];
  709. X     char new[MAXPATHLEN];
  710. X
  711. X#ifdef DEBUG
  712. X     printf("Looking for %s in %s\n", expression, base);
  713. X#endif
  714. X     found = (char **) malloc(0);
  715. X     *num_found = num = 0;
  716. X
  717. X     dirp = opendir(base);
  718. X     if (! dirp)
  719. X      return(found);
  720. X
  721. X     readdir(dirp); readdir(dirp); /* get rid of . and .. */
  722. X     
  723. X     strcpy(first, reg_firstpart(expression, rest));
  724. X     re_comp(first);
  725. X
  726. X     for (dp = readdir(dirp); dp != NULL; dp = readdir(dirp)) {
  727. X      if (re_exec(dp->d_name) && *rest) {
  728. X           strcpy(new, append(base, dp->d_name));
  729. X           next = find_deleted_matches(new, rest, &num_next);
  730. X           add_arrays(&found, &num, &next, &num_next);
  731. X      }
  732. X      else if (is_deleted(dp->d_name)) if (re_exec(&dp->d_name[2])) {
  733. X           if (*rest) {
  734. X            strcpy(new, append(base, dp->d_name));
  735. X            next = find_deleted_matches(new, rest, &num_next);
  736. X            add_arrays(&found, &num, &next, &num_next);
  737. X           }
  738. X           else {
  739. X            found = add_str(found, num, append(base, dp->d_name));
  740. X            num++;
  741. X           }
  742. X      }
  743. X     }
  744. X     closedir(dirp);
  745. X     *num_found = num;
  746. X     return(found);
  747. X}
  748. X
  749. X
  750. X
  751. X
  752. X
  753. Xchar **find_matches(base, expression, num_found)
  754. Xchar *base, *expression;
  755. Xint *num_found;
  756. X{
  757. X     struct direct *dp;
  758. X     DIR *dirp;
  759. X     char **found;
  760. X     int num;
  761. X     char **next;
  762. X     int num_next;
  763. X     char first[MAXNAMLEN], rest[MAXPATHLEN];
  764. X     char new[MAXPATHLEN];
  765. X     
  766. X#ifdef DEBUG
  767. X     printf("Looking for %s in %s\n", expression, base);
  768. X#endif
  769. X     found = (char **) malloc(0);
  770. X     *num_found = num = 0;
  771. X
  772. X     dirp = opendir(base);
  773. X     if (! dirp)
  774. X      return(found);
  775. X
  776. X     strcpy(first, reg_firstpart(expression, rest));
  777. X
  778. X     for (dp = readdir(dirp); dp != NULL; dp = readdir(dirp)) {
  779. X      re_comp(first);
  780. X      if (re_exec(dp->d_name)) {
  781. X           if (*rest) {
  782. X            strcpy(new, append(base, dp->d_name));
  783. X            next = find_matches(new, rest, &num_next);
  784. X            add_arrays(&found, &num, &next, &num_next);
  785. X           }
  786. X           else {
  787. X            found = add_str(found, num, append(base, dp->d_name));
  788. X            num++;
  789. X           }
  790. X      }
  791. X      else if (is_deleted(dp->d_name)) if (re_exec(&dp->d_name[2])) {
  792. X           if (*rest) {
  793. X            strcpy(new, append(base, dp->d_name));
  794. X            next = find_matches(new, rest, &num_next);
  795. X            add_arrays(&found, &num, &next, &num_next);
  796. X           }
  797. X           else {
  798. X            found = add_str(found, num, append(base, dp->d_name));
  799. X            num++;
  800. X           }
  801. X      }
  802. X     }
  803. X     closedir(dirp);
  804. X     *num_found = num;
  805. X     return(found);
  806. X}
  807. X
  808. X
  809. X
  810. X
  811. X
  812. X
  813. X
  814. Xchar **find_recurses(base, num_found)
  815. Xchar *base;
  816. Xint *num_found;
  817. X{
  818. X     DIR *dirp;
  819. X     struct direct *dp;
  820. X     char newname[MAXPATHLEN];
  821. X     char **found, **new_found;
  822. X     int found_num, new_found_num;
  823. X     struct stat stat_buf;
  824. X     
  825. X#ifdef DEBUG
  826. X     printf("Looking for subs of %s\n", base);
  827. X#endif
  828. X     found = (char **) malloc(0);
  829. X     *num_found = found_num = 0;
  830. X     
  831. X     dirp = opendir(base);
  832. X     if (! dirp)
  833. X      return(found);
  834. X
  835. X     readdir(dirp); readdir(dirp); /* get rid of . and .. */
  836. X
  837. X     for (dp = readdir(dirp); dp != NULL; dp = readdir(dirp)) {
  838. X      strcpy(newname, append(base, dp->d_name));
  839. X      found = add_str(found, found_num, newname);
  840. X      found_num++;
  841. X      if (lstat(newname, &stat_buf))
  842. X           continue;
  843. X      if ((stat_buf.st_mode & S_IFMT) == S_IFDIR) {
  844. X           new_found = find_recurses(newname, &new_found_num);
  845. X           add_arrays(&found, &found_num, &new_found, &new_found_num);
  846. X      }
  847. X     }
  848. X     closedir(dirp);
  849. X     *num_found = found_num;
  850. X     return(found);
  851. X}
  852. X
  853. X
  854. X
  855. X
  856. X
  857. X
  858. Xchar **find_deleted_recurses(base, num_found)
  859. Xchar *base;
  860. Xint *num_found;
  861. X{
  862. X     DIR *dirp;
  863. X     struct direct *dp;
  864. X     char newname[MAXPATHLEN];
  865. X     char **found, **new_found;
  866. X     int found_num, new_found_num;
  867. X     struct stat stat_buf;
  868. X     
  869. X     found = (char **) malloc(0);
  870. X     *num_found = found_num = 0;
  871. X     
  872. X     dirp = opendir(base);
  873. X     if (! dirp)
  874. X      return(found);
  875. X
  876. X     readdir(dirp); readdir(dirp); /* get rid of . and .. */
  877. X
  878. X     for (dp = readdir(dirp); dp != NULL; dp = readdir(dirp)) {
  879. X      strcpy(newname, append(base, dp->d_name));
  880. X      
  881. X      if (is_deleted(dp->d_name)) {
  882. X           found = add_str(found, found_num, newname);
  883. X           found_num++;
  884. X      }
  885. X      if (lstat(newname, &stat_buf)) {
  886. X           continue;
  887. X      }
  888. X      if ((stat_buf.st_mode & S_IFMT) == S_IFDIR) {
  889. X           new_found = find_deleted_recurses(newname, &new_found_num);
  890. X           add_arrays(&found, &found_num, &new_found, &new_found_num);
  891. X      }
  892. X     }
  893. X     closedir(dirp);
  894. X     *num_found = found_num;
  895. X     return(found);
  896. X}
  897. X
  898. X
  899. X
  900. X
  901. X
  902. X
  903. Xchar **find_contents(base, num_found)
  904. Xchar *base;
  905. Xint *num_found;
  906. X{
  907. X     DIR *dirp;
  908. X     struct direct *dp;
  909. X     char **found;
  910. X     int num;
  911. X
  912. X#ifdef DEBUG
  913. X     printf("Looking for contents of %s\n", base);
  914. X#endif
  915. X     found = (char **) malloc(0);
  916. X     *num_found = num = 0;
  917. X   
  918. X     dirp = opendir(base);
  919. X     if (! dirp)
  920. X      return(found);
  921. X
  922. X     readdir(dirp); readdir(dirp); /* get rid of . and .. */
  923. X
  924. X     for (dp = readdir(dirp); dp != NULL; dp = readdir(dirp)) {
  925. X      found = add_str(found, num, append(base, dp->d_name));
  926. X      num += 1;
  927. X     }
  928. X     closedir(dirp);
  929. X     *num_found = num;
  930. X     return(found);
  931. X}
  932. X
  933. X
  934. X     
  935. Xchar **find_deleted_contents(base, num_found)
  936. Xchar *base;
  937. Xint *num_found;
  938. X{
  939. X     DIR *dirp;
  940. X     struct direct *dp;
  941. X     char **found;
  942. X     int num;
  943. X
  944. X#ifdef DEBUG
  945. X     printf("Looking for deleted contents of %s\n", base);
  946. X#endif
  947. X     found = (char **) malloc(0);
  948. X     *num_found = num = 0;
  949. X   
  950. X     dirp = opendir(base);
  951. X     if (! dirp)
  952. X      return(found);
  953. X
  954. X     readdir(dirp); readdir(dirp); /* get rid of . and .. */
  955. X
  956. X     for (dp = readdir(dirp); dp != NULL; dp = readdir(dirp)) {
  957. X      if (is_deleted(dp->d_name)) {
  958. X           found = add_str(found, num, append(base, dp->d_name));
  959. X           num += 1;
  960. X      }
  961. X     }
  962. X     closedir(dirp);
  963. X     *num_found = num;
  964. X     return(found);
  965. X}
  966. X
  967. X
  968. X
  969. X
  970. Xchar **find_deleted_contents_recurs(base, num_found)
  971. Xchar *base;
  972. Xint *num_found;
  973. X{
  974. X     DIR *dirp;
  975. X     struct direct *dp;
  976. X     char **found;
  977. X     int num;
  978. X     struct stat stat_buf;
  979. X     char newname[MAXPATHLEN];
  980. X     char **new_found;
  981. X     int new_found_num;
  982. X     
  983. X#ifdef DEBUG
  984. X     printf("Looking for recursive deleted contents of %s\n", base);
  985. X#endif
  986. X     found = (char **) malloc(0);
  987. X     *num_found = num = 0;
  988. X   
  989. X     dirp = opendir(base);
  990. X     if (! dirp)
  991. X      return(found);
  992. X
  993. X     readdir(dirp); readdir(dirp); /* get rid of . and .. */
  994. X
  995. X     for (dp = readdir(dirp); dp != NULL; dp = readdir(dirp)) {
  996. X      if (is_deleted(dp->d_name)) {
  997. X           strcpy(newname, append(base, dp->d_name));
  998. X           found = add_str(found, num, newname);
  999. X           num += 1;
  1000. X           if (lstat(newname, &stat_buf))
  1001. X            continue;
  1002. X           if ((stat_buf.st_mode & S_IFMT) == S_IFDIR) {
  1003. X            new_found = find_recurses(newname, &new_found_num);
  1004. X            add_arrays(&found, &num, &new_found, &new_found_num);
  1005. X           }
  1006. X      }
  1007. X     }
  1008. X     closedir(dirp);
  1009. X     *num_found = num;
  1010. X     return(found);
  1011. X}
  1012. X     
  1013. X
  1014. X
  1015. X/*
  1016. X * returns true if the filename has no regular expression wildcards in
  1017. X * it.  That means no non-quoted dots or asterisks.  Assumes a
  1018. X * null-terminated string, and a valid regular expression.
  1019. X */
  1020. Xint no_wildcards(name)
  1021. Xchar *name;
  1022. X{
  1023. X     do {
  1024. X      switch (*name) {
  1025. X      case '\\':
  1026. X           name++;
  1027. X           break;
  1028. X      case '.':
  1029. X           return(0);
  1030. X      case '*':
  1031. X           return(0);
  1032. X      }
  1033. X     } while (*++name);
  1034. X     return(1);
  1035. X}
  1036. END_OF_FILE
  1037. if test 12106 -ne `wc -c <'pattern.c'`; then
  1038.     echo shar: \"'pattern.c'\" unpacked with wrong size!
  1039. fi
  1040. # end of 'pattern.c'
  1041. fi
  1042. echo shar: End of archive 4 \(of 6\).
  1043. cp /dev/null ark4isdone
  1044. MISSING=""
  1045. for I in 1 2 3 4 5 6 ; do
  1046.     if test ! -f ark${I}isdone ; then
  1047.     MISSING="${MISSING} ${I}"
  1048.     fi
  1049. done
  1050. if test "${MISSING}" = "" ; then
  1051.     echo You have unpacked all 6 archives.
  1052.     rm -f ark[1-9]isdone
  1053. else
  1054.     echo You still need to unpack the following archives:
  1055.     echo "        " ${MISSING}
  1056. fi
  1057. ##  End of shell archive.
  1058. exit 0
  1059.  
  1060. -- 
  1061. Please send comp.sources.unix-related mail to rsalz@uunet.uu.net.
  1062.  
  1063.  
  1064.